﻿Option Explicit On
Option Strict On

Imports System
Imports System.ServiceModel

Imports ACOMDirector
Imports ACOMDirector.Framework.Hardware

Namespace Framework.Hardware.Remoting

    ''' <summary>
    ''' The proxy class implementing the IStateManager contract
    ''' </summary>
    ''' <remarks></remarks>
    <ServiceBehavior(InstanceContextMode:=ServiceModel.InstanceContextMode.Single, ConcurrencyMode:=ConcurrencyMode.Multiple)> _
    Friend Class StateManagerProxy
        Implements IStateManager

#Region " Private Members "

        Private m_EventSubscribers As Generic.List(Of IStateManagerCallbacks) 'List to track subscribers to callback events
        Private WithEvents m_StateManager As StateManager 'The real state manager instance

#End Region

#Region " Constructor "

        ''' <summary>
        ''' Friend Constructor 
        ''' </summary>
        ''' <remarks></remarks>
        Friend Sub New(ByVal ComPort As String, ByVal SupportsPowerOn As Boolean, ByVal DeterminingOperateMode As Boolean, ByVal RemotePowerOnMechanism As RemotePowerOnSystem)
            m_EventSubscribers = New Generic.List(Of IStateManagerCallbacks)
            m_StateManager = New StateManager(ComPort, SupportsPowerOn, DeterminingOperateMode, RemotePowerOnMechanism)
        End Sub

#End Region

#Region " Public Methods "

        ''' <summary>
        ''' Subscribes a local instance to the callback events
        ''' </summary>
        ''' <param name="Callback"></param>
        ''' <remarks></remarks>
        Friend Sub SubscribeEventsLocal(ByVal Callback As IStateManagerCallbacks)
            m_EventSubscribers.Add(Callback)
        End Sub

#End Region

#Region " IStateManager Implementation "

        Public Sub Connect() Implements IStateManager.Connect
            m_StateManager.Connect()
        End Sub

        Public Sub Disconnect() Implements IStateManager.Disconnect
            m_StateManager.Disconnect()
        End Sub

        Public Sub OnOff() Implements IStateManager.OnOff
            m_StateManager.OnOff()
        End Sub

        Public Sub OperateStandby() Implements IStateManager.OperateStandby
            m_StateManager.OperateStandby()
        End Sub

        Public Sub SelectAntenna0() Implements IStateManager.SelectAntenna0
            m_StateManager.SelectAntenna0()
        End Sub

        Public Sub SelectAntenna1() Implements IStateManager.SelectAntenna1
            m_StateManager.SelectAntenna1()
        End Sub

        Public Sub SelectAntenna2() Implements IStateManager.SelectAntenna2
            m_StateManager.SelectAntenna2()
        End Sub

        Public Sub SelectAntenna3() Implements IStateManager.SelectAntenna3
            m_StateManager.SelectAntenna3()
        End Sub

        Public Sub SelectAntenna4() Implements IStateManager.SelectAntenna4
            m_StateManager.SelectAntenna4()
        End Sub

        Public Sub SelectAntenna5() Implements IStateManager.SelectAntenna5
            m_StateManager.SelectAntenna5()
        End Sub

        Public Sub SelectAntenna6() Implements IStateManager.SelectAntenna6
            m_StateManager.SelectAntenna6()
        End Sub

        Public Sub SelectAntenna7() Implements IStateManager.SelectAntenna7
            m_StateManager.SelectAntenna7()
        End Sub

        Public Sub SelectAntenna8() Implements IStateManager.SelectAntenna8
            m_StateManager.SelectAntenna8()
        End Sub

        Public Sub SelectAntenna9() Implements IStateManager.SelectAntenna9
            m_StateManager.SelectAntenna9()
        End Sub

        Public Sub SetMetricA(Metric As MeasurementMetricType) Implements IStateManager.SetMetricA
            m_StateManager.SetMetricA(Metric)
        End Sub

        Public Sub SetMetricB(Metric As MeasurementMetricType) Implements IStateManager.SetMetricB
            m_StateManager.SetMetricB(Metric)
        End Sub

        Public Sub StartMeasuring(MetricA As MeasurementMetricType, MetricB As MeasurementMetricType) Implements IStateManager.StartMeasuring
            m_StateManager.StartMeasuring(MetricA, MetricB)
        End Sub

        Public Sub StopMeasuring() Implements IStateManager.StopMeasuring
            m_StateManager.StopMeasuring()
        End Sub

        Public Function GetState() As AmplifierState Implements IStateManager.GetState
            Return m_StateManager.State
        End Function

        Public Function GetUIState() As UIState Implements IStateManager.GetUIState
            Return m_StateManager.UIState
        End Function

        Public Function GetComPort() As String Implements IStateManager.GetCOMPort
            Return m_StateManager.COMPort
        End Function

        Public Function GetCOMPortOpen() As Boolean Implements IStateManager.GetCOMPortOpen
            Return m_StateManager.COMPortOpen
        End Function

        Public Function GetSupportsRemotePowerOn() As Boolean Implements IStateManager.GetSupportsRemotePowerOn
            Return m_StateManager.SupportsRemotePowerOn
        End Function

        Public Sub SetComPort(value As String) Implements IStateManager.SetCOMPort
            m_StateManager.COMPort = value
        End Sub

        ''' <summary>
        ''' Subscribes the caller to the callback events
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub SubscribeEvents() Implements IStateManager.SubscribeEvents
            'Get the callback object from the calling client
            Dim callback As IStateManagerCallbacks = OperationContext.Current.GetCallbackChannel(Of IStateManagerCallbacks)()

            'Subscribe the caller from the events
            If Not m_EventSubscribers.Contains(callback) Then
                m_EventSubscribers.Add(callback)
            End If
        End Sub

        ''' <summary>
        ''' Unsubscribes the caller from the callback events
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub UnsubscribeEvents() Implements IStateManager.UnsubscribeEvents
            'Get the callback object from the calling client
            Dim callback As IStateManagerCallbacks = OperationContext.Current.GetCallbackChannel(Of IStateManagerCallbacks)()

            'Unsubscribe the caller from the events
            If m_EventSubscribers.Contains(callback) Then
                m_EventSubscribers.Remove(callback)
            End If
        End Sub

#End Region

#Region " Event Dispatchers "

        Private Sub m_StateManager_ForwardPowerLedChanged(sender As Object, e As PowerLedEventArgs) Handles m_StateManager.ForwardPowerLedChanged
            If m_EventSubscribers.Count = 0 Then Return

            'Track Dead Callback handlers
            Dim DeadCallbackHandlers As New Generic.List(Of IStateManagerCallbacks)

            'Dispatch the event
            For Each CallbackHandler As IStateManagerCallbacks In m_EventSubscribers
                Try
                    'CallbackHandler.ForwardPowerLedChangedCallback(e)
                    Dim LambdaCallbackHandler As IStateManagerCallbacks = CallbackHandler
                    CallbackHandler.BeginOnForwardPowerLedChanged(e, (Sub(ar As IAsyncResult) LambdaCallbackHandler.EndOnForwardPowerLedChanged(ar)), Nothing)
                Catch ex As System.ServiceModel.CommunicationException
                    DeadCallbackHandlers.Add(CallbackHandler)
                End Try
            Next

            'Remove any dead callback handlers
            If DeadCallbackHandlers.Count > 0 Then
                For Each item As IStateManagerCallbacks In DeadCallbackHandlers
                    m_EventSubscribers.Remove(item)
                Next
            End If
        End Sub

        Private Sub m_StateManager_ReflectedPowerLedChanged(sender As Object, e As PowerLedEventArgs) Handles m_StateManager.ReflectedPowerLedChanged
            If m_EventSubscribers.Count = 0 Then Return

            'Track Dead Callback handlers
            Dim DeadCallbackHandlers As New Generic.List(Of IStateManagerCallbacks)

            'Dispatch the event
            For Each CallbackHandler As IStateManagerCallbacks In m_EventSubscribers
                Try
                    'CallbackHandler.ReflectedPowerLedChangedCallback(e)
                    Dim LambdaCallbackHandler As IStateManagerCallbacks = CallbackHandler
                    CallbackHandler.BeginOnReflectedPowerLedChanged(e, (Sub(ar As IAsyncResult) LambdaCallbackHandler.EndOnReflectedPowerLedChanged(ar)), Nothing)
                Catch ex As System.ServiceModel.CommunicationException
                    DeadCallbackHandlers.Add(CallbackHandler)
                End Try
            Next

            'Remove any dead callback handlers
            If DeadCallbackHandlers.Count > 0 Then
                For Each item As IStateManagerCallbacks In DeadCallbackHandlers
                    m_EventSubscribers.Remove(item)
                Next
            End If
        End Sub

        Private Sub m_StateManager_StateChanged(sender As Object, e As System.EventArgs) Handles m_StateManager.StateChanged
            If m_EventSubscribers.Count = 0 Then Return

            'Track Dead Callback handlers
            Dim DeadCallbackHandlers As New Generic.List(Of IStateManagerCallbacks)

            'Dispatch the event
            For Each CallbackHandler As IStateManagerCallbacks In m_EventSubscribers
                Try
                    'CallbackHandler.StateChangedCallback()
                    Dim LambdaCallbackHandler As IStateManagerCallbacks = CallbackHandler
                    CallbackHandler.BeginOnStateChanged((Sub(ar As IAsyncResult) LambdaCallbackHandler.EndOnStateChanged(ar)), Nothing)
                Catch ex As CommunicationException
                    DeadCallbackHandlers.Add(CallbackHandler)
                End Try
            Next

            'Remove any dead callback handlers
            If DeadCallbackHandlers.Count > 0 Then
                For Each item As IStateManagerCallbacks In DeadCallbackHandlers
                    m_EventSubscribers.Remove(item)
                Next
            End If
        End Sub

#End Region

    End Class

End Namespace